- /* sifiiadd.cpp by K.Tsuru */
- // function ID = 420
- // bugfix in version 2.16
- /****************************************
- SInteger class
- It provides the addition result = m + n.
- The signs of m and n can be different.
- **************************************/
- #ifndef SN_H
- #include "sn.h"
- #endif
-
- void IIAdd(const SInteger& m, const SInteger& n, SInteger& result){
- int s = m.Sign(420) * n.Sign(420), c;
- if(!s){
- if(!m.Sign()) result = n;
- else result = m;
- return;
- } else if(s < 0){ //different sign
- c = LLCompare(m, n);
- if(c > 0){ // m + n = m - (-n)
- // Notice the case "&result == &m" or "&result == &n".
- SInteger temp(n); // bugfix ver. 2.16 on Jul 31, 2002
- temp.ChangeSign(); //temp = -n
-
- IISub(m, temp, result); // |m| > |n|. The sign is the same as that of m.
- }else if(c < 0){ // m + n = n - (-m)
- SInteger temp(m); // bugfix ver. 2.16 on Jul 31, 2002
- temp.ChangeSign(); //temp = -m
-
- IISub(n, temp, result); // |m| < |n|. The sign is the same as that of m.
- } else result.SetZero(); // c = 0 : |m| = |n|
- return;
- }
-
- // m and n have the same sign.
- //It makes |m| >= |n|.
- if(m.Head() < n.Head()){ IIAdd(n, m, result); return; }
-
- // Here |m| > |n| ("c > 0 && mh >= nh") and evaluate m + n.
- // m and n have the same sign and the figures of m is greater than or equal to that of n.
- if(n.aHead == 0){ // n has one figure.
- // bugfix ver. 2.16
- if(n.Sign() > 0) IsAdd(m, n(0), result); // 0 < n < m, m + n = m + n(0)
- else IsSub(m, n(0), result); // m < n < 0, m + n = m - n(0)
-
- result.SetSign( m.Sign() );
- return;
- }
-
- uint mh = m.Head(), nh = n.Head(); // mh >= nh
- uint rt = min( m.Tail(), n.Tail() );
-
- /*
- Neither IIAdd(L, z, L); nor IIAdd(z, L, L);
- it allocates the memory of "result" and initializes it.
- */
- if( (&m != &result) && (&n != &result) ){
- result.valloc(m.Size(), -1);
- if(rt) result.figure.clear(0, rt -1u);
- result.figure.clear(mh+1u);
- } else result.Reserve(mh);//IIAdd(z, L, L); z > L(=result)
-
- const fType* mv = m.ReadFigures();
- const fType* nv = n.ReadFigures();
- fType* rv = result.figure.Elements();
- #ifndef NDEBUG
- result.figure(mh);
- #endif
- // rv[] = mv[] + nv[]
- fType u = 0; //carry = 0 or 1
- register uint i;
-
- for(i = rt; i <= nh ; i++) {
- u += mv[i] + nv[i];
- rv[i] = u & BRADIX1;
- u >>= BRADIX_BITS; // 0 or 1
- }
- //processing upper figures
- for( ; u && (i<= mh) ; i++){//A few times to u = 0 except special case.
- u += mv[i];
- rv[i] = u & BRADIX1;
- u >>= BRADIX_BITS;
- }
- if(u){ //One figure increases.
- mh++;
- result.Reserve(mh); // check over flow
- rv = result.figure.Elements(); //Reserve() maybe changed "rv".
- result.figure[mh] = u;
- } else if( (mh >= i) && (rv != mv) ){ //no carry
- memcpy(rv + i, mv + i, sizeof(fType)*(mh-i+1));
- }
- //It gets figure positions.
- while( !rv[rt] ) rt++;
-
- result.aHead = mh; result.aTail = rt;
- result.SetSign( m.Sign() );
- //If the figures decrease it reduces the size, considering the case that
- //IIAdd(m, n, result); result>m.
- if( 2u*(result.aHead+1) <= result.figure.size() ) result.DoCutDown();
- }
sifiiadd.cpp : last modifiled at 2017/03/13 14:31:59(3,143 bytes)
created at 2016/04/25 14:53:17
The creation time of this html file is 2017/10/25 11:09:45 (Wed Oct 25 11:09:45 2017).